﻿//统一文件为utf-8编码编译
#pragma execution_character_set("utf-8")
///////////////////////////////////////////////////////////////////////////
// 文件名:     heartbeatmanage.cpp
// 描述:
// 作者:      颜磊
// 创建时间:   2024-06-08 23:44
///////////////////////////////////////////////////////////////////////////
#include "heartbeatmanage.h"
#include "sddl.h"
//#include <QDebug>

SharedMemory::SharedMemory()
{

}

SharedMemory::~SharedMemory()
{

}

HANDLE SharedMemory::openSharedMemory(string name, int size)
{
    name = "Global\\" + name;
    const char* shareSSDL = "D:P(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GA;;;IU)";
    //创建安全描述符
    SECURITY_ATTRIBUTES security;
    ZeroMemory(&security, sizeof(security));
    security.nLength = sizeof(security);
    ConvertStringSecurityDescriptorToSecurityDescriptorA(
                shareSSDL ,
                SDDL_REVISION,
                &security.lpSecurityDescriptor,
                NULL);
    //以指定的安全描述符去创建共享内存
    HANDLE hMapFile= CreateFileMappingA(
                INVALID_HANDLE_VALUE,   // 物理文件句柄
                &security,   // 默认安全级别
                PAGE_READWRITE,   // 可读可写
                0,   // 高位文件大小
                size,   // 低位文件大小
                name.c_str()   // 共享内存名称
                );
    LocalFree(security.lpSecurityDescriptor);
    return hMapFile;
}

bool SharedMemory::setSharedMemoryData(string name, char *data, int size)
{
    name = "Global\\" + name;
    // 打开共享的文件对象
    HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, NULL, name.c_str());
    if (hMapFile)
    {
        LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        // 将共享内存数据拷贝出来
        memcpy(lpBase,data, size);
        // 解除文件映射
        UnmapViewOfFile(lpBase);
        // 关闭内存映射文件对象句柄
        CloseHandle(hMapFile);
        return true;
    }
    else
    {
        return false;
    }
}

bool SharedMemory::getSharedMemoryData(string name, char *data, int size)
{
    name = "Global\\" + name;
    memset(data,0,size);
    // 打开共享的文件对象
    HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, NULL, name.c_str());

    if (hMapFile)
    {
        LPVOID lpBase = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
        // 将共享内存数据拷贝出来
        memcpy(data, lpBase, size);
        // 解除文件映射
        UnmapViewOfFile(lpBase);
        // 关闭内存映射文件对象句柄
        CloseHandle(hMapFile);
        return true;
    }
    else
    {
        return false;
    }

}

void SharedMemory::closeSharedMemory(HANDLE hMapFile)
{
    // 关闭内存映射文件对象句柄
    if(hMapFile)
        CloseHandle(hMapFile);
}

HeartbeatManage::HeartbeatManage()
{
    errno_t	err = 0;
    char	fileName[100] = { 0 };
    char    processFullName[_MAX_PATH] = { 0 };
    char    processName[0x40] = { 0 };
    DWORD   dwpid = 0;
    char *  tmp1 = NULL;
    char *  tmp2 = NULL;

    dwpid = GetCurrentProcessId();
    GetModuleFileNameA(NULL, processFullName, _MAX_PATH); //进程完整路径

    tmp1 = strrchr((char *)processFullName, '\\');
    tmp2 = strrchr((char *)processFullName, '.');
    memcpy(processName, tmp1 + 1, min(tmp2 - tmp1 - 1, 0x40)); //截取得进程名

    heartbeat_msg = processName;
    heartbeat_msg += "_heartbeat";
}

HeartbeatManage::~HeartbeatManage()
{
    for (std::map<string, HANDLE>::iterator it = heartbeatMap.begin(); it != heartbeatMap.end();)
    {
        sharedMemory.closeSharedMemory(it->second);
        it = heartbeatMap.erase(it);//或者mp.erase(it++)
    }
}


int HeartbeatManage::checkHeartbeat(string name)
{
    //不存则创建
    if(heartbeatMap.find(name) == heartbeatMap.end()){
        HANDLE hMapFile = sharedMemory.openSharedMemory(name,sizeof (HeartbeatMsg));
        heartbeatMap[name] = hMapFile;
    }
    //校验心跳信息
    HeartbeatMsg heartbeatMsg;
    if(sharedMemory.getSharedMemoryData(name,(char*)&heartbeatMsg,sizeof (HeartbeatMsg))){
        //进行校验
        time_t nowTime;
        time(&nowTime);
        if(heartbeatMsg.exitFlag)return 2;
        if(nowTime - heartbeatMsg.timestamp < 10) return 1;
    }else{
        //异常处理
        printf("getSharedMemoryData error");
        return 0;
    }
}

void HeartbeatManage::start()
{
    beatThread = thread(&HeartbeatManage::beatRun,this);
}

void HeartbeatManage::stop()
{
    isRun = false;
    if(beatThread.joinable())
        beatThread.join();
}

void HeartbeatManage::beat()
{
    HeartbeatMsg heartbeatMsg;
    time(&heartbeatMsg.timestamp); //获取从1970至今过了多少秒，存入time_t类型的timep
    //qDebug() << "upTime" << heartbeat_msg.c_str() << heartbeatMsg.timestamp;
    sharedMemory.setSharedMemoryData(heartbeat_msg,(char*)&heartbeatMsg,sizeof (HeartbeatMsg));
}

void HeartbeatManage::exit()
{
    HeartbeatMsg heartbeatMsg;
    time(&heartbeatMsg.timestamp); //获取从1970至今过了多少秒，存入time_t类型的timep
    heartbeatMsg.exitFlag = true;
    sharedMemory.setSharedMemoryData(heartbeat_msg,(char*)&heartbeatMsg,sizeof (HeartbeatMsg));
}

void HeartbeatManage::beatRun()
{
    isRun = true;
    while (isRun) {
        beat();
        Sleep(1000);
    }
}
